# -*- coding: utf-8 -*-
"""
    xfree.cli.plugins
    ~~~~~~~~~~~~~~~~~~~
    文件描述：这个模块包含所有插件相关的命令。
    作者：xfree
    邮箱：cy_83k@qq.com
"""

import os
import sys

import click
from flask import current_app
from flask.cli import with_appcontext

from xfree.cli.main import xfree
from xfree.cli.utils import get_cookiecutter, validate_plugin
from xfree.extensions import db
from xfree.plugins.models import PluginRegistry, PluginStore
from xfree.plugins.utils import remove_zombie_plugins_from_db


@xfree.group()
def plugins():
    """插件命令子组。如果你想运行迁移或进行一些国际化相关的操作，请查看相应的命令子组。"""
    pass


@plugins.command("list")
@with_appcontext
def list_plugins():
    """列出所有已安装的插件。"""
    enabled_plugins = current_app.pluggy.list_plugin_distinfo()
    if len(enabled_plugins) > 0:
        click.secho("[+] 已启用的插件：", fg="blue", bold=True)
        for plugin in enabled_plugins:
            p_mod = plugin[0]
            p_dist = plugin[1]
            click.secho(
                "\t- {}\t({}), 版本 {}".format(
                    current_app.pluggy.get_name(p_mod).title(),
                    p_dist.key,
                    p_dist.version,
                ),
                bold=True,
            )

    disabled_plugins = current_app.pluggy.list_disabled_plugins()
    if len(disabled_plugins) > 0:
        click.secho("[+] 已禁用的插件：", fg="yellow", bold=True)
        for plugin in disabled_plugins:
            p_mod = plugin[0]
            p_dist = plugin[1]
            click.secho(
                "\t- {}\t({}), 版本 {}".format(
                    p_mod.title(), p_dist.key, p_dist.version
                ),
                bold=True,
            )


@plugins.command("enable")
@click.argument("plugin_name")
@with_appcontext
def enable_plugin(plugin_name):
    """启用一个插件。"""
    validate_plugin(plugin_name)
    plugin = PluginRegistry.query.filter_by(name=plugin_name).first_or_404()

    if plugin.enabled:
        click.secho("插件 '{}' 已经启用。".format(plugin.name))
    else:
        plugin.enabled = True
        plugin.save()
        click.secho("[+] 插件 '{}' 已启用。".format(plugin.name), fg="green")


@plugins.command("disable")
@click.argument("plugin_name")
@with_appcontext
def disable_plugin(plugin_name):
    """禁用一个插件。"""
    validate_plugin(plugin_name)
    plugin = PluginRegistry.query.filter_by(name=plugin_name).first_or_404()

    if not plugin.enabled:
        click.secho("插件 '{}' 已经禁用。".format(plugin.name))
    else:
        plugin.enabled = False
        plugin.save()
        click.secho("[+] 插件 '{}' 已禁用。".format(plugin.name), fg="green")


@plugins.command("install")
@click.argument("plugin_name")
@click.option(
    "--force",
    "-f",
    default=False,
    is_flag=True,
    help="覆盖现有设置"
)
def install(plugin_name, force):
    """安装一个插件（不进行迁移）。"""
    # 验证插件是否存在
    validate_plugin(plugin_name)
    plugin = PluginRegistry.query.filter_by(name=plugin_name).first_or_404()

    if not plugin.enabled:
        click.secho(
            "[+] 不能安装禁用的插件。请先启用 '{}' 插件。".format(plugin.name),
            fg="red",
        )
        sys.exit(0)

    if plugin.is_installable:
        plugin_module = current_app.pluggy.get_plugin(plugin.name)
        plugin.add_settings(plugin_module.SETTINGS, force)
        click.secho("[+] 插件已安装。", fg="green")
    else:
        click.secho("[+] 无需安装。", fg="green")


@plugins.command("uninstall")
@click.argument("plugin_name")
def uninstall(plugin_name):
    """卸载一个插件（不进行迁移）。"""
    validate_plugin(plugin_name)
    plugin = PluginRegistry.query.filter_by(name=plugin_name).first_or_404()

    if plugin.is_installed:
        PluginStore.query.filter_by(plugin_id=plugin.id).delete()
        db.session.commit()
        click.secho("[+] 插件已卸载。", fg="green")
    else:
        click.secho("[+] 无需卸载。", fg="green")


@plugins.command("cleanup")
@with_appcontext
def cleanup():
    """从 xfree 中移除僵尸插件。僵尸插件是指存在于数据库中但环境中已不存在的插件。"""
    deleted_plugins = remove_zombie_plugins_from_db()
    if len(deleted_plugins) > 0:
        click.secho(
            "[+] 已从 xfree 中移除以下僵尸插件：", fg="green", nl=False
        )
        click.secho("{}".format(", ".join(deleted_plugins)))
    else:
        click.secho("[+] 没有僵尸插件。", fg="green")


@plugins.command("new")
@click.option(
    "--template",
    "-t",
    type=click.STRING,
    default="https://github.com/sh4nks/cookiecutter-xfree-plugin",
    help="指向一个 cookiecutter 模板的路径或一个有效的 Git 仓库的路径。",
)
@click.option(
    "--out-dir",
    "-o",
    type=click.Path(),
    default=None,
    help="新 xfree 插件的保存位置。",
)
@click.option(
    "--force",
    "-f",
    is_flag=True,
    default=False,
    help="如果输出目录存在，则覆盖其内容。",
)
def new_plugin(template, out_dir, force):
    """基于 cookiecutter 插件模板创建一个新插件。默认模板为：https://github.com/sh4nks/cookiecutter-xfree-plugin。它可以接受文件系统中的有效路径或包含 cookiecutter 模板的 Git 仓库的 URL。"""
    cookiecutter = get_cookiecutter()

    if out_dir is None:
        out_dir = click.prompt("保存插件的位置", default=os.path.abspath("."))

    r = cookiecutter(template, output_dir=out_dir, overwrite_if_exists=force)
    click.secho("[+] 在 {} 创建了新插件。".format(r), fg="green", bold=True)